package com.carbeauty.common.response;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;

import java.time.LocalDateTime;

/**
 * API统一响应包装类
 * 
 * 统一API响应格式:
 * - 成功响应包含数据
 * - 失败响应包含错误信息
 * - 包含响应时间戳
 * - 支持分页数据
 * 
 * @author CarBeauty Team
 */
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ApiResponse<T> {
    
    /**
     * 响应状态码
     */
    private Integer code;
    
    /**
     * 响应消息
     */
    private String message;
    
    /**
     * 响应数据
     */
    private T data;
    
    /**
     * 响应时间戳
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime timestamp;
    
    /**
     * 请求路径
     */
    private String path;
    
    /**
     * 分页信息
     */
    private PageInfo pageInfo;
    
    // ==================== 构造方法 ====================
    
    public ApiResponse() {
        this.timestamp = LocalDateTime.now();
    }
    
    public ApiResponse(Integer code, String message) {
        this();
        this.code = code;
        this.message = message;
    }
    
    public ApiResponse(Integer code, String message, T data) {
        this();
        this.code = code;
        this.message = message;
        this.data = data;
    }
    
    // ==================== 静态工厂方法 ====================
    
    /**
     * 成功响应
     */
    public static <T> ApiResponse<T> success() {
        return new ApiResponse<>(200, "操作成功");
    }
    
    /**
     * 成功响应带数据
     */
    public static <T> ApiResponse<T> success(T data) {
        return new ApiResponse<>(200, "操作成功", data);
    }
    
    /**
     * 成功响应带消息和数据
     */
    public static <T> ApiResponse<T> success(String message, T data) {
        return new ApiResponse<>(200, message, data);
    }
    
    /**
     * 失败响应
     */
    public static <T> ApiResponse<T> error(String message) {
        return new ApiResponse<>(500, message);
    }
    
    /**
     * 失败响应带状态码
     */
    public static <T> ApiResponse<T> error(Integer code, String message) {
        return new ApiResponse<>(code, message);
    }
    
    /**
     * 参数错误响应
     */
    public static <T> ApiResponse<T> badRequest(String message) {
        return new ApiResponse<>(400, message);
    }
    
    /**
     * 未授权响应
     */
    public static <T> ApiResponse<T> unauthorized(String message) {
        return new ApiResponse<>(401, message != null ? message : "未授权访问");
    }
    
    /**
     * 禁止访问响应
     */
    public static <T> ApiResponse<T> forbidden(String message) {
        return new ApiResponse<>(403, message != null ? message : "禁止访问");
    }
    
    /**
     * 资源不存在响应
     */
    public static <T> ApiResponse<T> notFound(String message) {
        return new ApiResponse<>(404, message != null ? message : "资源不存在");
    }
    
    // ==================== 分页响应 ====================
    
    /**
     * 分页成功响应
     */
    public static <T> ApiResponse<T> page(T data, long total, int page, int size) {
        ApiResponse<T> response = success(data);
        response.setPageInfo(new PageInfo(total, page, size));
        return response;
    }
    
    /**
     * 分页成功响应带消息
     */
    public static <T> ApiResponse<T> page(String message, T data, long total, int page, int size) {
        ApiResponse<T> response = success(message, data);
        response.setPageInfo(new PageInfo(total, page, size));
        return response;
    }
    
    // ==================== 链式调用方法 ====================
    
    /**
     * 设置请求路径
     */
    public ApiResponse<T> path(String path) {
        this.path = path;
        return this;
    }
    
    /**
     * 设置分页信息
     */
    public ApiResponse<T> page(long total, int page, int size) {
        this.pageInfo = new PageInfo(total, page, size);
        return this;
    }
    
    // ==================== Getter/Setter ====================
    
    public Integer getCode() {
        return code;
    }
    
    public void setCode(Integer code) {
        this.code = code;
    }
    
    public String getMessage() {
        return message;
    }
    
    public void setMessage(String message) {
        this.message = message;
    }
    
    public T getData() {
        return data;
    }
    
    public void setData(T data) {
        this.data = data;
    }
    
    public LocalDateTime getTimestamp() {
        return timestamp;
    }
    
    public void setTimestamp(LocalDateTime timestamp) {
        this.timestamp = timestamp;
    }
    
    public String getPath() {
        return path;
    }
    
    public void setPath(String path) {
        this.path = path;
    }
    
    public PageInfo getPageInfo() {
        return pageInfo;
    }
    
    public void setPageInfo(PageInfo pageInfo) {
        this.pageInfo = pageInfo;
    }
    
    // ==================== 业务判断方法 ====================
    
    /**
     * 判断是否成功
     */
    public boolean isSuccess() {
        return code != null && code == 200;
    }
    
    /**
     * 判断是否失败
     */
    public boolean isError() {
        return !isSuccess();
    }
    
    // ==================== 分页信息内部类 ====================
    
    /**
     * 分页信息
     */
    @JsonInclude(JsonInclude.Include.NON_NULL)
    public static class PageInfo {
        
        /**
         * 总记录数
         */
        private Long total;
        
        /**
         * 当前页码（从0开始）
         */
        private Integer page;
        
        /**
         * 每页大小
         */
        private Integer size;
        
        /**
         * 总页数
         */
        private Integer totalPages;
        
        /**
         * 是否有下一页
         */
        private Boolean hasNext;
        
        /**
         * 是否有上一页
         */
        private Boolean hasPrevious;
        
        /**
         * 是否为第一页
         */
        private Boolean isFirst;
        
        /**
         * 是否为最后一页
         */
        private Boolean isLast;
        
        public PageInfo() {}
        
        public PageInfo(Long total, Integer page, Integer size) {
            this.total = total;
            this.page = page;
            this.size = size;
            
            // 计算总页数
            this.totalPages = size > 0 ? (int) Math.ceil((double) total / size) : 0;
            
            // 计算分页状态
            this.hasNext = page < totalPages - 1;
            this.hasPrevious = page > 0;
            this.isFirst = page == 0;
            this.isLast = page == totalPages - 1;
        }
        
        // Getter/Setter方法
        public Long getTotal() { return total; }
        public void setTotal(Long total) { this.total = total; }
        
        public Integer getPage() { return page; }
        public void setPage(Integer page) { this.page = page; }
        
        public Integer getSize() { return size; }
        public void setSize(Integer size) { this.size = size; }
        
        public Integer getTotalPages() { return totalPages; }
        public void setTotalPages(Integer totalPages) { this.totalPages = totalPages; }
        
        public Boolean getHasNext() { return hasNext; }
        public void setHasNext(Boolean hasNext) { this.hasNext = hasNext; }
        
        public Boolean getHasPrevious() { return hasPrevious; }
        public void setHasPrevious(Boolean hasPrevious) { this.hasPrevious = hasPrevious; }
        
        public Boolean getIsFirst() { return isFirst; }
        public void setIsFirst(Boolean isFirst) { this.isFirst = isFirst; }
        
        public Boolean getIsLast() { return isLast; }
        public void setIsLast(Boolean isLast) { this.isLast = isLast; }
    }
}
